package high.concurrent.strategy;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * 标准分片下：水平分库策略
 * RangeShardingAlgorithm<Long> Long是因为分片键是Long型的
 */
public class CustomDBPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {

    /**
     * @param dataSourceNames 数据源集合
     *                      在分库时值为所有分片库的集合 databaseNames
     *                      分表时为对应分片库中所有分片表的集合 tablesNames(是表名的集合，比如product_order_0)
     *
     * @param shardingValue  分片属性，包括
    *                                  logicTableName 为逻辑表，
    *                                  columnName 分片健（字段），
    *                                  value 为从 SQL 中解析出的分片健的值
     * @return
     */
    @Override
        public String doSharding(Collection<String> dataSourceNames, PreciseShardingValue<String> shardingValue) {

        // 获取SQL解析的分片键第一位(库位)
        String firstChar = shardingValue.getValue().toString().substring(0, 1);

        // 遍历所有分片表名，由于没有逻辑库这个概念，所以只能用循环，但是有逻辑表，所以分表直接获取逻辑表名即可
        for(String dataSourceName : dataSourceNames){

            // 获取库名最后一位
            String dbLastChar = dataSourceName.substring(dataSourceName.length() - 1);

            // 和库名最后一个字符比较，判断如果分片键取模后的结果和库名最后一个字符是否相同，表示该数据应该映射到该库上，直接返回该库名即可
            // 因为库名都是ds0， ds1,所以最后一个字符就是0，1 取模后的结果就和0，1比较
            if(dbLastChar.equals(firstChar)){
                return dataSourceName;
            }
        }
        return null;
    }
}
